package com.wisdom.system.api.core.job;


import com.wisdom.system.entity.job.JobTask;
import com.wisdom.system.common.exception.LogicException;
import com.wisdom.system.common.factory.ClassFactory;
import com.wisdom.system.service.job.JobTaskService;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class JobSchedule {
    private static final Logger LOGGER = LoggerFactory.getLogger(JobSchedule.class);

    private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();

    private static String JOB_GROUP_NAME = "DEFAULT_JOB_GROUP_NAME";
    private static String TRIGGER_GROUP_NAME = "DEFAULT_TRIGGER_GROUP_NAME";

    private JobSchedule() {
    }

    @Autowired
    JobTaskService jobTaskService;

    @PostConstruct
    public void initTask() {
        jobTaskService.getJobTaskStartList().forEach(jobTask -> startJob(jobTask));
    }

    //项目启动时自动启动的项目
    public static void startJob(JobTask jobTask) {
        try {
            String clazzName = "com.wisdom.system.api.core.job." + jobTask.getClazzName();
            Class clazz = ClassFactory.getClassObj(clazzName);
            if (clazz == null){
               throw LogicException.of("job触发类错误！");
            }
            JobSchedule.addJob(jobTask.getCode(), clazz, jobTask.getFkCronExpression());
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    //停止任务（移除任务）
    public static void stopJob(JobTask jobTask) {
        try {
            JobSchedule.removeJob(jobTask.getCode());
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param jobName 任务名
     * @param clazz   任务
     * @param cron    时间设置，参考quartz说明文档
     * @throws SchedulerException
     * @Description: 添加一个定时任务，使用默认的任务组名，触发器名，触发器组名
     */
    public static void addJob(String jobName, Class clazz, String cron) throws SchedulerException {
        Scheduler scheduler = gSchedulerFactory.getScheduler();
        // 用于描叙Job实现类及其他的一些静态信息，构建一个作业实例
        JobDetail jobDetail = JobBuilder.newJob(clazz)
                .withIdentity(jobName, JOB_GROUP_NAME).build();
        // 构建一个触发器，规定触发的规则
        Trigger trigger = TriggerBuilder.newTrigger()// 创建一个新的TriggerBuilder来规范一个触发器
                .withIdentity(jobName, TRIGGER_GROUP_NAME)// 给触发器起一个名字和组名
                .startNow()// 立即执行
                .withSchedule(CronScheduleBuilder.cronSchedule(cron)) // 触发器的执行时间
                .build();// 产生触发器

        scheduler.scheduleJob(jobDetail, trigger);
        LOGGER.debug("添加任务:{},{},{}", jobName, clazz, cron);
        // 启动
        if (!scheduler.isShutdown()) {
            scheduler.start();
        }
    }

    /**
     * @param jobName          任务名
     * @param jobGroupName     任务组名
     * @param triggerName      触发器名
     * @param triggerGroupName 触发器组名
     * @param clazz            任务
     * @param cron             时间设置，参考quartz说明文档
     * @Description: 添加一个定时任务
     */
    public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class clazz, String cron) throws SchedulerException {
        Scheduler scheduler = gSchedulerFactory.getScheduler();
        // 用于描叙Job实现类及其他的一些静态信息，构建一个作业实例
        JobDetail jobDetail = JobBuilder.newJob(clazz)
                .withIdentity(jobName, jobGroupName).build();
        // 构建一个触发器，规定触发的规则
        Trigger trigger = TriggerBuilder.newTrigger()// 创建一个新的TriggerBuilder来规范一个触发器
                .withIdentity(jobName, triggerGroupName)// 给触发器起一个名字和组名
                .startNow()// 立即执行
                .withSchedule(CronScheduleBuilder.cronSchedule(cron)) // 触发器的执行时间
                .build();// 产生触发器

        scheduler.scheduleJob(jobDetail, trigger);
        LOGGER.debug("添加任务:{},{},{},{},{},{}", jobName, jobGroupName, triggerName, triggerGroupName, clazz, cron);
        // 启动
        if (!scheduler.isShutdown()) {
            scheduler.start();
        }

    }

    /**
     * @param jobName
     * @param cron
     * @throws SchedulerException
     * @Description: 修改一个任务的触发时间(使用默认的任务组名 ， 触发器名 ， 触发器组名)
     */
    public static void modifyJobTime(String jobName, String cron) throws SchedulerException {
        Scheduler scheduler = gSchedulerFactory.getScheduler();
        TriggerKey triggerKey = new TriggerKey(jobName, TRIGGER_GROUP_NAME);
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        if (trigger == null) {
            return;
        }
        String oldTime = trigger.getCronExpression();
        if (!oldTime.equalsIgnoreCase(cron)) {
            JobDetail jobDetail = scheduler.getJobDetail(new JobKey(jobName,
                    JOB_GROUP_NAME));
            Class objJobClass = jobDetail.getJobClass();
            removeJob(jobName);
            addJob(jobName, objJobClass, cron);
            LOGGER.debug("修改任务:{},{}", jobName, cron);
        }
    }

    /**
     * @param jobName
     * @throws SchedulerException
     * @Description: 移除一个任务(使用默认的任务组名 ， 触发器名 ， 触发器组名)
     */
    public static void removeJob(String jobName) throws SchedulerException {
        Scheduler scheduler = gSchedulerFactory.getScheduler();
        JobKey jobKey = new JobKey(jobName, TRIGGER_GROUP_NAME);
        // 停止触发器
        scheduler.pauseJob(jobKey);
        scheduler.unscheduleJob(new TriggerKey(jobName, TRIGGER_GROUP_NAME));// 移除触发器
        scheduler.deleteJob(jobKey);// 删除任务
        LOGGER.debug("移除任务:{}", jobName);
    }

    /**
     * 移除任务
     *
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     * @throws SchedulerException
     */
    public static void removeJob(String jobName, String jobGroupName,
                                 String triggerName, String triggerGroupName)
            throws SchedulerException {
        Scheduler scheduler = gSchedulerFactory.getScheduler();
        JobKey jobKey = new JobKey(jobName, jobGroupName);
        // 停止触发器
        scheduler.pauseJob(jobKey);
        scheduler.unscheduleJob(new TriggerKey(jobName, triggerGroupName));// 移除触发器
        scheduler.deleteJob(jobKey);// 删除任务
        LOGGER.debug("移除任务:{},{},{},{},{},{}", jobName, jobGroupName, triggerName, triggerGroupName);
    }

    /**
     * 启动所有任务
     *
     * @throws SchedulerException
     */
    public static void startJobs() throws SchedulerException {
        Scheduler scheduler = gSchedulerFactory.getScheduler();
        scheduler.start();
        LOGGER.debug("启动所有任务");
    }

    /**
     * 关闭所有定时任务
     *
     * @throws SchedulerException
     */
    public static void shutdownJobs() throws SchedulerException {
        Scheduler scheduler = gSchedulerFactory.getScheduler();
        if (!scheduler.isShutdown()) {
            scheduler.shutdown();
            LOGGER.debug("关闭所有任务");
        }
    }
}

